home *** CD-ROM | disk | FTP | other *** search
- ; FormNumString.asm
- ;-------------------
- ; by Mike™ Scanlin 29 Dec 1986
-
- Xref FormNumString,GetANumber
-
- ;============
- FormNumString
- ;============
- ; format the string representation of a number (integer or real)
- ; according to a format string.
- ; input: A0 points to string of a number (which should be in a
- ; space big enough for formatting result)
- ; A1 points to format string
- ; syntax of format string is [',']d[d]['.'[d[d]]] where ''
- ; denote a constant char and d denotes a digit '0'..'9'
- ; there is no length byte for these strings.
- ; valid strings invalid strings
- ; 3 230. (230 too big [99 max])
- ; 4.0 or 4. .0 (need a d before '.')
- ; ,3.4 ,.4 (need a d between ',.')
- ; ,12.20 0.123 (123 too big)
- ; output: A0 points to formatted string of a number
- ; A1 points to first byte after format string
-
- MOVEM.L D0-D5/A2,-(SP)
- CMPI.B #',',(A1)
- BNE.S @6
- ADDA #1,A1
- ;do commas
- ;first find out if there is a decimal point in the string
- MOVEQ #0,D0
- MOVE.B (A0),D0 ;length of string
- MOVE D0,D2 ;save in case it's and int
- SUBQ #1,D0 ;loop control
- ;D0 counts how many digits from the end of the string to the
- ;decimal point (including the decimal point -- which is why
- ;it starts out as 1 and not 0). If the number is an int, then D0=0
- MOVEQ #1,D1
- @1 CMPI.B #'.',1(A0,D0) ;find a dec point, it's a real
- BEQ.S @2
- ADDQ #1,D1
- DBRA D0,@1
- ;it's an integer
- MOVE D2,D0
- MOVEQ #0,D1
- ;now add some commas
- @2 MOVE D1,D5 ;save length of fraction
- MOVEQ #3,D2 ;# of digits until next comma
- SUBQ #1,D0
- @3 ADDQ #1,D1 ;total len, from end to cur pos
- SUBQ #1,D2
- BNE.S @5
- MOVE D0,D3
- MOVE.B (A0,D0),D0
- BSR IsItADigit ;test next digit
- BNE.S @6
- MOVE D3,D0
- ;move some chars, add a comma, increase string length.
- MOVE D1,D4 ;loop control
- SUBQ #1,D4
- LEA 1(A0,D0),A2
- @4 MOVE.B (A2,D4),1(A2,D4)
- DBRA D4,@4
- MOVE.B #',',(A2)
- ADDI.B #1,(A0)
- ADDQ #1,D1 ;for the comma
- MOVEQ #3,D2 ;reset counter
- @5 DBRA D0,@3
- ;get next byte of format string
- @6 BSR.S GetANumber ;D0 = q
- BMI.S @16 ;no q provided -- leave
- MOVEQ #0,D2
- MOVE.B (A0),D2 ;length of string
- MOVE D2,D1
- SUB D5,D1 ;D1=len of quotient now
- SUB D1,D0
- BMI.S @10
- BEQ.S @10
- ADD.B D0,(A0) ;increase length by D0 spaces
- ;add D0 # of preceeding spaces
- @7 LEA 1(A0,D0),A2
- SUBQ #1,D2
- @8 MOVE.B 1(A0,D2),(A2,D2)
- DBRA D2,@8
- SUBQ #1,D0
- @9 MOVE.B #' ',1(A0,D0)
- DBRA D0,@9
- ;do remainder
- @10 CMPI.B #'.',(A1)
- BNE.S @16
- ADDA #1,A1
- ;make sure there is a decimal point already
- LEA 1(A0),A2
- MOVEQ #0,D0
- MOVE.B (A0),D0
- SUBQ #1,D0
- @11 CMP.B #'.',(A2)+
- BEQ.S @12
- DBRA D0,@11
- MOVE.B #'.',(A2)+
- ADD.B #1,(A0)
- @12 BSR.S GetANumber
- BMI.S @16 ;no r provided -- leave
- ;D0 is how many digits they want. D5 is what we've already got.
- @13 SUBQ #1,D5
- @14 CMP D5,D0
- BEQ.S @16
- BPL.S @15
- SUB.B #1,(A0)
- BRA.S @13
- @15 MOVE.B #'0',(A2,D5) ;add a zero
- ADD.B #1,(A0)
- ADDQ #1,D5
- BRA.S @14
- @16 MOVEM.L (SP)+,A2/D0-D5
- RTS
-
- ;=========
- GetANumber
- ;=========
- ; convert a one or two digit ASCII integer into its numerical form
- ; input: A1 points to digit(s)
- ; output: D0 is the decimal equivalent (-1 if A1 didn't point to a digit)
- ; A1 points to byte after digit(s)
- ; Z and N flags reflect the value of D0
- MOVEM.L D1-D2,-(SP)
- MOVEQ #0,D0
- MOVE.B (A1),D0
- @1 BSR.S IsItADigit
- BEQ.S @2
- MOVEQ #-1,D0
- BRA.S @4
- @2 ADDA #1,A1
- MOVE D0,D1 ;save first digit
- MOVE.B (A1),D0
- BSR.S IsItADigit
- BEQ.S @3
- MOVE D1,D0
- BRA.S @4
- @3 ADDA #1,A1
- ADD D1,D1 ;multiply first digit by 10
- MOVE D1,D2
- ADD D2,D2
- ADD D2,D2
- ADD D2,D1
- ADD D1,D0 ;add to second digit
- @4 MOVEM.L (SP)+,D1-D2
- TST D0
- RTS
-
- ;=========
- IsItADigit
- ;=========
- ; If the ASCII byte in D0 is in '0'..'9' it's value [0..9]
- ; is returned in D0. If D0 is a digit, all flags are set.
- CMPI.B #'0',D0
- BLT.S @1
- CMPI.B #'9',D0
- BGT.S @1
- SUBI.B #'0',D0
- MOVE #-1,CCR ;set all flags
- RTS
- @1 MOVE #0,CCR ;clear all flags
- RTS
-